home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume17 / pax / part06 < prev    next >
Encoding:
Internet Message Format  |  1989-02-02  |  36.4 KB

  1. Subject:  v17i079:  Usenix/IEEE POSIX replacement for TAR and CPIO, Part06/06
  2. Newsgroups: comp.sources.unix
  3. Approved: rsalz@uunet.UU.NET
  4.  
  5. Submitted-by: Mark H. Colburn <mark@jhereg.jhereg.mn.org>
  6. Posting-number: Volume 17, Issue 79
  7. Archive-name: pax/part06
  8.  
  9. #! /bin/sh
  10. # This is a shell archive.  Remove anything before this line, then unpack
  11. # it by saving it into a file and typing "sh file".  To overwrite existing
  12. # files, type "sh file -c".  You can also feed this as standard input via
  13. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  14. # will see the following message at the end:
  15. #        "End of archive 6 (of 6)."
  16. # Contents:  regexp.c Makefile
  17. # Wrapped by mark@jhereg on Tue Dec 27 19:38:04 1988
  18. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  19. if test -f regexp.c -a "${1}" != "-c" ; then 
  20.   echo shar: Will not over-write existing file \"regexp.c\"
  21. else
  22. echo shar: Extracting \"regexp.c\" \(30611 characters\)
  23. sed "s/^X//" >regexp.c <<'END_OF_regexp.c'
  24. X/* $Source: /u/mark/src/pax/RCS/regexp.c,v $
  25. X *
  26. X * $Revision: 1.1 $
  27. X *
  28. X * regexp.c - regular expression matching
  29. X *
  30. X * DESCRIPTION
  31. X *
  32. X *    Underneath the reformatting and comment blocks which were added to 
  33. X *    make it consistent with the rest of the code, you will find a
  34. X *    modified version of Henry Specer's regular expression library.
  35. X *    Henry's functions were modified to provide the minimal regular
  36. X *    expression matching, as required by P1003.  Henry's code was
  37. X *    copyrighted, and copy of the copyright message and restrictions
  38. X *    are provided, verbatim, below:
  39. X *
  40. X *    Copyright (c) 1986 by University of Toronto.
  41. X *    Written by Henry Spencer.  Not derived from licensed software.
  42. X *
  43. X *    Permission is granted to anyone to use this software for any
  44. X *    purpose on any computer system, and to redistribute it freely,
  45. X *    subject to the following restrictions:
  46. X *
  47. X *    1. The author is not responsible for the consequences of use of
  48. X *         this software, no matter how awful, even if they arise
  49. X *       from defects in it.
  50. X *
  51. X *    2. The origin of this software must not be misrepresented, either
  52. X *       by explicit claim or by omission.
  53. X *
  54. X *    3. Altered versions must be plainly marked as such, and must not
  55. X *       be misrepresented as being the original software.
  56. X *
  57. X *     Beware that some of this code is subtly aware of the way operator
  58. X *     precedence is structured in regular expressions.  Serious changes in
  59. X *     regular-expression syntax might require a total rethink.
  60. X *
  61. X * AUTHORS
  62. X *
  63. X *     Mark H. Colburn, NAPS International (mark@jhereg.mn.org)
  64. X *     Henry Spencer, University of Torronto (henry@utzoo.edu)
  65. X *
  66. X * Sponsored by The USENIX Association for public distribution. 
  67. X *
  68. X * $Log:    regexp.c,v $
  69. X * Revision 1.1  88/12/23  18:02:32  mark
  70. X * Initial revision
  71. X * 
  72. X */
  73. X
  74. X/* Headers */
  75. X
  76. X#include "pax.h"
  77. X
  78. X#ifndef lint
  79. Xstatic char    *Ident = "$Id: regexp.c,v 1.1 88/12/23 18:02:32 mark Rel $";
  80. X#endif
  81. X
  82. X
  83. X/*
  84. X * The "internal use only" fields in regexp.h are present to pass info from
  85. X * compile to execute that permits the execute phase to run lots faster on
  86. X * simple cases.  They are:
  87. X *
  88. X * regstart    char that must begin a match; '\0' if none obvious
  89. X * reganch    is the match anchored (at beginning-of-line only)?
  90. X * regmust    string (pointer into program) that match must include, or NULL
  91. X * regmlen    length of regmust string
  92. X *
  93. X * Regstart and reganch permit very fast decisions on suitable starting points
  94. X * for a match, cutting down the work a lot.  Regmust permits fast rejection
  95. X * of lines that cannot possibly match.  The regmust tests are costly enough
  96. X * that regcomp() supplies a regmust only if the r.e. contains something
  97. X * potentially expensive (at present, the only such thing detected is * or +
  98. X * at the start of the r.e., which can involve a lot of backup).  Regmlen is
  99. X * supplied because the test in regexec() needs it and regcomp() is computing
  100. X * it anyway.
  101. X */
  102. X
  103. X/*
  104. X * Structure for regexp "program".  This is essentially a linear encoding
  105. X * of a nondeterministic finite-state machine (aka syntax charts or
  106. X * "railroad normal form" in parsing technology).  Each node is an opcode
  107. X * plus a "nxt" pointer, possibly plus an operand.  "Nxt" pointers of
  108. X * all nodes except BRANCH implement concatenation; a "nxt" pointer with
  109. X * a BRANCH on both ends of it is connecting two alternatives.  (Here we
  110. X * have one of the subtle syntax dependencies:  an individual BRANCH (as
  111. X * opposed to a collection of them) is never concatenated with anything
  112. X * because of operator precedence.)  The operand of some types of node is
  113. X * a literal string; for others, it is a node leading into a sub-FSM.  In
  114. X * particular, the operand of a BRANCH node is the first node of the branch.
  115. X * (NB this is *not* a tree structure:  the tail of the branch connects
  116. X * to the thing following the set of BRANCHes.)  The opcodes are:
  117. X */
  118. X
  119. X/* definition    number    opnd?    meaning */
  120. X#define    END    0        /* no    End of program. */
  121. X#define    BOL    1        /* no    Match "" at beginning of line. */
  122. X#define    EOL    2        /* no    Match "" at end of line. */
  123. X#define    ANY    3        /* no    Match any one character. */
  124. X#define    ANYOF    4        /* str    Match any character in this string. */
  125. X#define    ANYBUT    5        /* str    Match any character not in this
  126. X                 * string. */
  127. X#define    BRANCH    6        /* node    Match this alternative, or the
  128. X                 * nxt... */
  129. X#define    BACK    7        /* no    Match "", "nxt" ptr points backward. */
  130. X#define    EXACTLY    8        /* str    Match this string. */
  131. X#define    NOTHING    9        /* no    Match empty string. */
  132. X#define    STAR    10        /* node    Match this (simple) thing 0 or more
  133. X                 * times. */
  134. X#define    OPEN    20        /* no    Mark this point in input as start of
  135. X                 * #n. */
  136. X /* OPEN+1 is number 1, etc. */
  137. X#define    CLOSE    30        /* no    Analogous to OPEN. */
  138. X
  139. X/*
  140. X * Opcode notes:
  141. X *
  142. X * BRANCH    The set of branches constituting a single choice are hooked
  143. X *        together with their "nxt" pointers, since precedence prevents
  144. X *        anything being concatenated to any individual branch.  The
  145. X *        "nxt" pointer of the last BRANCH in a choice points to the
  146. X *        thing following the whole choice.  This is also where the
  147. X *        final "nxt" pointer of each individual branch points; each
  148. X *        branch starts with the operand node of a BRANCH node.
  149. X *
  150. X * BACK        Normal "nxt" pointers all implicitly point forward; BACK
  151. X *        exists to make loop structures possible.
  152. X *
  153. X * STAR        complex '*', are implemented as circular BRANCH structures 
  154. X *        using BACK.  Simple cases (one character per match) are 
  155. X *        implemented with STAR for speed and to minimize recursive 
  156. X *        plunges.
  157. X *
  158. X * OPEN,CLOSE    ...are numbered at compile time.
  159. X */
  160. X
  161. X/*
  162. X * A node is one char of opcode followed by two chars of "nxt" pointer.
  163. X * "Nxt" pointers are stored as two 8-bit pieces, high order first.  The
  164. X * value is a positive offset from the opcode of the node containing it.
  165. X * An operand, if any, simply follows the node.  (Note that much of the
  166. X * code generation knows about this implicit relationship.)
  167. X *
  168. X * Using two bytes for the "nxt" pointer is vast overkill for most things,
  169. X * but allows patterns to get big without disasters.
  170. X */
  171. X#define    OP(p)    (*(p))
  172. X#define    NEXT(p)    (((*((p)+1)&0377)<<8) + (*((p)+2)&0377))
  173. X#define    OPERAND(p)    ((p) + 3)
  174. X
  175. X/*
  176. X * Utility definitions.
  177. X */
  178. X
  179. X#define    FAIL(m)    { regerror(m); return(NULL); }
  180. X#define    ISMULT(c)    ((c) == '*')
  181. X#define    META    "^$.[()|*\\"
  182. X#ifndef CHARBITS
  183. X#define    UCHARAT(p)    ((int)*(unsigned char *)(p))
  184. X#else
  185. X#define    UCHARAT(p)    ((int)*(p)&CHARBITS)
  186. X#endif
  187. X
  188. X/*
  189. X * Flags to be passed up and down.
  190. X */
  191. X#define    HASWIDTH    01    /* Known never to match null string. */
  192. X#define    SIMPLE        02    /* Simple enough to be STAR operand. */
  193. X#define    SPSTART        04    /* Starts with * */
  194. X#define    WORST        0    /* Worst case. */
  195. X
  196. X/*
  197. X * Global work variables for regcomp().
  198. X */
  199. Xstatic char    *regparse;    /* Input-scan pointer. */
  200. Xstatic int      regnpar;    /* () count. */
  201. Xstatic char     regdummy;
  202. Xstatic char    *regcode;    /* Code-emit pointer; ®dummy = don't. */
  203. Xstatic long     regsize;    /* Code size. */
  204. X
  205. X/*
  206. X * Forward declarations for regcomp()'s friends.
  207. X */
  208. X#ifndef STATIC
  209. X#define    STATIC    static
  210. X#endif
  211. XSTATIC char    *reg();
  212. XSTATIC char    *regbranch();
  213. XSTATIC char    *regpiece();
  214. XSTATIC char    *regatom();
  215. XSTATIC char    *regnode();
  216. XSTATIC char    *regnext();
  217. XSTATIC void     regc();
  218. XSTATIC void     reginsert();
  219. XSTATIC void     regtail();
  220. XSTATIC void     regoptail();
  221. X#ifdef STRCSPN
  222. XSTATIC int      strcspn();
  223. X#endif
  224. X
  225. X/*
  226. X - regcomp - compile a regular expression into internal code
  227. X *
  228. X * We can't allocate space until we know how big the compiled form will be,
  229. X * but we can't compile it (and thus know how big it is) until we've got a
  230. X * place to put the code.  So we cheat:  we compile it twice, once with code
  231. X * generation turned off and size counting turned on, and once "for real".
  232. X * This also means that we don't allocate space until we are sure that the
  233. X * thing really will compile successfully, and we never have to move the
  234. X * code and thus invalidate pointers into it.  (Note that it has to be in
  235. X * one piece because free() must be able to free it all.)
  236. X *
  237. X * Beware that the optimization-preparation code in here knows about some
  238. X * of the structure of the compiled regexp.
  239. X */
  240. Xregexp *regcomp(exp)
  241. Xchar           *exp;
  242. X{
  243. X    register regexp *r;
  244. X    register char  *scan;
  245. X    register char  *longest;
  246. X    register int    len;
  247. X    int             flags;
  248. X    extern char    *malloc();
  249. X
  250. X    if (exp == NULL)
  251. X    FAIL("NULL argument");
  252. X
  253. X    /* First pass: determine size, legality. */
  254. X    regparse = exp;
  255. X    regnpar = 1;
  256. X    regsize = 0L;
  257. X    regcode = ®dummy;
  258. X    regc(MAGIC);
  259. X    if (reg(0, &flags) == NULL)
  260. X    return (NULL);
  261. X
  262. X    /* Small enough for pointer-storage convention? */
  263. X    if (regsize >= 32767L)    /* Probably could be 65535L. */
  264. X    FAIL("regexp too big");
  265. X
  266. X    /* Allocate space. */
  267. X    r = (regexp *) malloc(sizeof(regexp) + (unsigned) regsize);
  268. X    if (r == NULL)
  269. X    FAIL("out of space");
  270. X
  271. X    /* Second pass: emit code. */
  272. X    regparse = exp;
  273. X    regnpar = 1;
  274. X    regcode = r->program;
  275. X    regc(MAGIC);
  276. X    if (reg(0, &flags) == NULL)
  277. X    return (NULL);
  278. X
  279. X    /* Dig out information for optimizations. */
  280. X    r->regstart = '\0';        /* Worst-case defaults. */
  281. X    r->reganch = 0;
  282. X    r->regmust = NULL;
  283. X    r->regmlen = 0;
  284. X    scan = r->program + 1;    /* First BRANCH. */
  285. X    if (OP(regnext(scan)) == END) {    /* Only one top-level choice. */
  286. X    scan = OPERAND(scan);
  287. X
  288. X    /* Starting-point info. */
  289. X    if (OP(scan) == EXACTLY)
  290. X        r->regstart = *OPERAND(scan);
  291. X    else if (OP(scan) == BOL)
  292. X        r->reganch++;
  293. X
  294. X    /*
  295. X     * If there's something expensive in the r.e., find the longest
  296. X     * literal string that must appear and make it the regmust.  Resolve
  297. X     * ties in favor of later strings, since the regstart check works
  298. X     * with the beginning of the r.e. and avoiding duplication
  299. X     * strengthens checking.  Not a strong reason, but sufficient in the
  300. X     * absence of others. 
  301. X     */
  302. X    if (flags & SPSTART) {
  303. X        longest = NULL;
  304. X        len = 0;
  305. X        for (; scan != NULL; scan = regnext(scan))
  306. X        if (OP(scan) == EXACTLY && strlen(OPERAND(scan)) >= len) {
  307. X            longest = OPERAND(scan);
  308. X            len = strlen(OPERAND(scan));
  309. X        }
  310. X        r->regmust = longest;
  311. X        r->regmlen = len;
  312. X    }
  313. X    }
  314. X    return (r);
  315. X}
  316. X
  317. X/*
  318. X - reg - regular expression, i.e. main body or parenthesized thing
  319. X *
  320. X * Caller must absorb opening parenthesis.
  321. X *
  322. X * Combining parenthesis handling with the base level of regular expression
  323. X * is a trifle forced, but the need to tie the tails of the branches to what
  324. X * follows makes it hard to avoid.
  325. X */
  326. Xstatic char *reg(paren, flagp)
  327. Xint             paren;        /* Parenthesized? */
  328. Xint            *flagp;
  329. X{
  330. X    register char  *ret;
  331. X    register char  *br;
  332. X    register char  *ender;
  333. X    register int    parno;
  334. X    int             flags;
  335. X
  336. X    *flagp = HASWIDTH;        /* Tentatively. */
  337. X
  338. X    /* Make an OPEN node, if parenthesized. */
  339. X    if (paren) {
  340. X    if (regnpar >= NSUBEXP)
  341. X        FAIL("too many ()");
  342. X    parno = regnpar;
  343. X    regnpar++;
  344. X    ret = regnode(OPEN + parno);
  345. X    } else
  346. X    ret = NULL;
  347. X
  348. X    /* Pick up the branches, linking them together. */
  349. X    br = regbranch(&flags);
  350. X    if (br == NULL)
  351. X    return (NULL);
  352. X    if (ret != NULL)
  353. X    regtail(ret, br);    /* OPEN -> first. */
  354. X    else
  355. X    ret = br;
  356. X    if (!(flags & HASWIDTH))
  357. X    *flagp &= ~HASWIDTH;
  358. X    *flagp |= flags & SPSTART;
  359. X    while (*regparse == '|') {
  360. X    regparse++;
  361. X    br = regbranch(&flags);
  362. X    if (br == NULL)
  363. X        return (NULL);
  364. X    regtail(ret, br);    /* BRANCH -> BRANCH. */
  365. X    if (!(flags & HASWIDTH))
  366. X        *flagp &= ~HASWIDTH;
  367. X    *flagp |= flags & SPSTART;
  368. X    }
  369. X
  370. X    /* Make a closing node, and hook it on the end. */
  371. X    ender = regnode((paren) ? CLOSE + parno : END);
  372. X    regtail(ret, ender);
  373. X
  374. X    /* Hook the tails of the branches to the closing node. */
  375. X    for (br = ret; br != NULL; br = regnext(br))
  376. X    regoptail(br, ender);
  377. X
  378. X    /* Check for proper termination. */
  379. X    if (paren && *regparse++ != ')') {
  380. X    FAIL("unmatched ()");
  381. X    } else if (!paren && *regparse != '\0') {
  382. X    if (*regparse == ')') {
  383. X        FAIL("unmatched ()");
  384. X    } else
  385. X        FAIL("junk on end");/* "Can't happen". */
  386. X    /* NOTREACHED */
  387. X    }
  388. X    return (ret);
  389. X}
  390. X
  391. X/*
  392. X - regbranch - one alternative of an | operator
  393. X *
  394. X * Implements the concatenation operator.
  395. X */
  396. Xstatic char  *regbranch(flagp)
  397. Xint            *flagp;
  398. X{
  399. X    register char  *ret;
  400. X    register char  *chain;
  401. X    register char  *latest;
  402. X    int             flags;
  403. X
  404. X    *flagp = WORST;        /* Tentatively. */
  405. X
  406. X    ret = regnode(BRANCH);
  407. X    chain = NULL;
  408. X    while (*regparse != '\0' && *regparse != '|' && *regparse != ')') {
  409. X    latest = regpiece(&flags);
  410. X    if (latest == NULL)
  411. X        return (NULL);
  412. X    *flagp |= flags & HASWIDTH;
  413. X    if (chain == NULL)    /* First piece. */
  414. X        *flagp |= flags & SPSTART;
  415. X    else
  416. X        regtail(chain, latest);
  417. X    chain = latest;
  418. X    }
  419. X    if (chain == NULL)        /* Loop ran zero times. */
  420. X    regnode(NOTHING);
  421. X
  422. X    return (ret);
  423. X}
  424. X
  425. X/*
  426. X - regpiece - something followed by possible [*]
  427. X *
  428. X * Note that the branching code sequence used for * is somewhat optimized:  
  429. X * they use the same NOTHING node as both the endmarker for their branch 
  430. X * list and the body of the last branch.  It might seem that this node could 
  431. X * be dispensed with entirely, but the endmarker role is not redundant.
  432. X */
  433. Xstatic char *regpiece(flagp)
  434. Xint            *flagp;
  435. X{
  436. X    register char  *ret;
  437. X    register char   op;
  438. X    register char  *nxt;
  439. X    int             flags;
  440. X
  441. X    ret = regatom(&flags);
  442. X    if (ret == NULL)
  443. X    return (NULL);
  444. X
  445. X    op = *regparse;
  446. X    if (!ISMULT(op)) {
  447. X    *flagp = flags;
  448. X    return (ret);
  449. X    }
  450. X    if (!(flags & HASWIDTH))
  451. X    FAIL("* operand could be empty");
  452. X    *flagp = (WORST | SPSTART);
  453. X
  454. X    if (op == '*' && (flags & SIMPLE))
  455. X    reginsert(STAR, ret);
  456. X    else if (op == '*') {
  457. X    /* Emit x* as (x&|), where & means "self". */
  458. X    reginsert(BRANCH, ret);    /* Either x */
  459. X    regoptail(ret, regnode(BACK));    /* and loop */
  460. X    regoptail(ret, ret);    /* back */
  461. X    regtail(ret, regnode(BRANCH));    /* or */
  462. X    regtail(ret, regnode(NOTHING));    /* null. */
  463. X    } 
  464. X    regparse++;
  465. X    if (ISMULT(*regparse))
  466. X    FAIL("nested *");
  467. X
  468. X    return (ret);
  469. X}
  470. X
  471. X/*
  472. X - regatom - the lowest level
  473. X *
  474. X * Optimization:  gobbles an entire sequence of ordinary characters so that
  475. X * it can turn them into a single node, which is smaller to store and
  476. X * faster to run.  Backslashed characters are exceptions, each becoming a
  477. X * separate node; the code is simpler that way and it's not worth fixing.
  478. X */
  479. Xstatic char *regatom(flagp)
  480. Xint            *flagp;
  481. X{
  482. X    register char  *ret;
  483. X    int             flags;
  484. X
  485. X    *flagp = WORST;        /* Tentatively. */
  486. X
  487. X    switch (*regparse++) {
  488. X    case '^':
  489. X    ret = regnode(BOL);
  490. X    break;
  491. X    case '$':
  492. X    ret = regnode(EOL);
  493. X    break;
  494. X    case '.':
  495. X    ret = regnode(ANY);
  496. X    *flagp |= HASWIDTH | SIMPLE;
  497. X    break;
  498. X    case '[':{
  499. X        register int    class;
  500. X        register int    classend;
  501. X
  502. X        if (*regparse == '^') {    /* Complement of range. */
  503. X        ret = regnode(ANYBUT);
  504. X        regparse++;
  505. X        } else
  506. X        ret = regnode(ANYOF);
  507. X        if (*regparse == ']' || *regparse == '-')
  508. X        regc(*regparse++);
  509. X        while (*regparse != '\0' && *regparse != ']') {
  510. X        if (*regparse == '-') {
  511. X            regparse++;
  512. X            if (*regparse == ']' || *regparse == '\0')
  513. X            regc('-');
  514. X            else {
  515. X            class = UCHARAT(regparse - 2) + 1;
  516. X            classend = UCHARAT(regparse);
  517. X            if (class > classend + 1)
  518. X                FAIL("invalid [] range");
  519. X            for (; class <= classend; class++)
  520. X                regc(class);
  521. X            regparse++;
  522. X            }
  523. X        } else
  524. X            regc(*regparse++);
  525. X        }
  526. X        regc('\0');
  527. X        if (*regparse != ']')
  528. X        FAIL("unmatched []");
  529. X        regparse++;
  530. X        *flagp |= HASWIDTH | SIMPLE;
  531. X    }
  532. X    break;
  533. X    case '(':
  534. X    ret = reg(1, &flags);
  535. X    if (ret == NULL)
  536. X        return (NULL);
  537. X    *flagp |= flags & (HASWIDTH | SPSTART);
  538. X    break;
  539. X    case '\0':
  540. X    case '|':
  541. X    case ')':
  542. X    FAIL("internal urp");    /* Supposed to be caught earlier. */
  543. X    break;
  544. X    case '*':
  545. X    FAIL("* follows nothing");
  546. X    break;
  547. X    case '\\':
  548. X    if (*regparse == '\0')
  549. X        FAIL("trailing \\");
  550. X    ret = regnode(EXACTLY);
  551. X    regc(*regparse++);
  552. X    regc('\0');
  553. X    *flagp |= HASWIDTH | SIMPLE;
  554. X    break;
  555. X    default:{
  556. X        register int    len;
  557. X        register char   ender;
  558. X
  559. X        regparse--;
  560. X        len = strcspn(regparse, META);
  561. X        if (len <= 0)
  562. X        FAIL("internal disaster");
  563. X        ender = *(regparse + len);
  564. X        if (len > 1 && ISMULT(ender))
  565. X        len--;        /* Back off clear of * operand. */
  566. X        *flagp |= HASWIDTH;
  567. X        if (len == 1)
  568. X        *flagp |= SIMPLE;
  569. X        ret = regnode(EXACTLY);
  570. X        while (len > 0) {
  571. X        regc(*regparse++);
  572. X        len--;
  573. X        }
  574. X        regc('\0');
  575. X    }
  576. X    break;
  577. X    }
  578. X
  579. X    return (ret);
  580. X}
  581. X
  582. X/*
  583. X - regnode - emit a node
  584. X */
  585. Xstatic char *regnode(op)
  586. Xchar            op;
  587. X{
  588. X    register char  *ret;
  589. X    register char  *ptr;
  590. X
  591. X    ret = regcode;
  592. X    if (ret == ®dummy) {
  593. X    regsize += 3;
  594. X    return (ret);
  595. X    }
  596. X    ptr = ret;
  597. X    *ptr++ = op;
  598. X    *ptr++ = '\0';        /* Null "nxt" pointer. */
  599. X    *ptr++ = '\0';
  600. X    regcode = ptr;
  601. X
  602. X    return (ret);
  603. X}
  604. X
  605. X/*
  606. X - regc - emit (if appropriate) a byte of code
  607. X */
  608. Xstatic void regc(b)
  609. Xchar            b;
  610. X{
  611. X    if (regcode != ®dummy)
  612. X    *regcode++ = b;
  613. X    else
  614. X    regsize++;
  615. X}
  616. X
  617. X/*
  618. X - reginsert - insert an operator in front of already-emitted operand
  619. X *
  620. X * Means relocating the operand.
  621. X */
  622. Xstatic void reginsert(op, opnd)
  623. Xchar            op;
  624. Xchar           *opnd;
  625. X{
  626. X    register char  *src;
  627. X    register char  *dst;
  628. X    register char  *place;
  629. X
  630. X    if (regcode == ®dummy) {
  631. X    regsize += 3;
  632. X    return;
  633. X    }
  634. X    src = regcode;
  635. X    regcode += 3;
  636. X    dst = regcode;
  637. X    while (src > opnd)
  638. X    *--dst = *--src;
  639. X
  640. X    place = opnd;        /* Op node, where operand used to be. */
  641. X    *place++ = op;
  642. X    *place++ = '\0';
  643. X    *place++ = '\0';
  644. X}
  645. X
  646. X/*
  647. X - regtail - set the next-pointer at the end of a node chain
  648. X */
  649. Xstatic void regtail(p, val)
  650. Xchar           *p;
  651. Xchar           *val;
  652. X{
  653. X    register char  *scan;
  654. X    register char  *temp;
  655. X    register int    offset;
  656. X
  657. X    if (p == ®dummy)
  658. X    return;
  659. X
  660. X    /* Find last node. */
  661. X    scan = p;
  662. X    for (;;) {
  663. X    temp = regnext(scan);
  664. X    if (temp == NULL)
  665. X        break;
  666. X    scan = temp;
  667. X    }
  668. X
  669. X    if (OP(scan) == BACK)
  670. X    offset = scan - val;
  671. X    else
  672. X    offset = val - scan;
  673. X    *(scan + 1) = (offset >> 8) & 0377;
  674. X    *(scan + 2) = offset & 0377;
  675. X}
  676. X
  677. X/*
  678. X - regoptail - regtail on operand of first argument; nop if operandless
  679. X */
  680. Xstatic void regoptail(p, val)
  681. Xchar           *p;
  682. Xchar           *val;
  683. X{
  684. X    /* "Operandless" and "op != BRANCH" are synonymous in practice. */
  685. X    if (p == NULL || p == ®dummy || OP(p) != BRANCH)
  686. X    return;
  687. X    regtail(OPERAND(p), val);
  688. X}
  689. X
  690. X/*
  691. X * regexec and friends
  692. X */
  693. X
  694. X/*
  695. X * Global work variables for regexec().
  696. X */
  697. Xstatic char    *reginput;    /* String-input pointer. */
  698. Xstatic char    *regbol;        /* Beginning of input, for ^ check. */
  699. Xstatic char   **regstartp;    /* Pointer to startp array. */
  700. Xstatic char   **regendp;    /* Ditto for endp. */
  701. X
  702. X/*
  703. X * Forwards.
  704. X */
  705. XSTATIC int      regtry();
  706. XSTATIC int      regmatch();
  707. XSTATIC int      regrepeat();
  708. X
  709. X#ifdef DEBUG
  710. Xint             regnarrate = 0;
  711. Xvoid            regdump();
  712. XSTATIC char    *regprop();
  713. X#endif
  714. X
  715. X/*
  716. X - regexec - match a regexp against a string
  717. X */
  718. Xint regexec(prog, string)
  719. Xregister regexp *prog;
  720. Xregister char  *string;
  721. X{
  722. X    register char  *s;
  723. X
  724. X    /* Be paranoid... */
  725. X    if (prog == NULL || string == NULL) {
  726. X    regerror("NULL parameter");
  727. X    return (0);
  728. X    }
  729. X    /* Check validity of program. */
  730. X    if (UCHARAT(prog->program) != MAGIC) {
  731. X    regerror("corrupted program");
  732. X    return (0);
  733. X    }
  734. X    /* If there is a "must appear" string, look for it. */
  735. X    if (prog->regmust != NULL) {
  736. X    s = string;
  737. X    while ((s = strchr(s, prog->regmust[0])) != NULL) {
  738. X        if (strncmp(s, prog->regmust, prog->regmlen) == 0)
  739. X        break;        /* Found it. */
  740. X        s++;
  741. X    }
  742. X    if (s == NULL)        /* Not present. */
  743. X        return (0);
  744. X    }
  745. X    /* Mark beginning of line for ^ . */
  746. X    regbol = string;
  747. X
  748. X    /* Simplest case:  anchored match need be tried only once. */
  749. X    if (prog->reganch)
  750. X    return (regtry(prog, string));
  751. X
  752. X    /* Messy cases:  unanchored match. */
  753. X    s = string;
  754. X    if (prog->regstart != '\0')
  755. X    /* We know what char it must start with. */
  756. X    while ((s = strchr(s, prog->regstart)) != NULL) {
  757. X        if (regtry(prog, s))
  758. X        return (1);
  759. X        s++;
  760. X    }
  761. X    else
  762. X    /* We don't -- general case. */
  763. X    do {
  764. X        if (regtry(prog, s))
  765. X        return (1);
  766. X    } while (*s++ != '\0');
  767. X
  768. X    /* Failure. */
  769. X    return (0);
  770. X}
  771. X
  772. X/*
  773. X - regtry - try match at specific point
  774. X */
  775. X#ifdef __STDC__
  776. X
  777. Xstatic int regtry(regexp *prog, char *string)
  778. X
  779. X#else
  780. X
  781. Xstatic int regtry(prog, string)
  782. Xregexp         *prog;
  783. Xchar           *string;
  784. X
  785. X#endif
  786. X{
  787. X    register int    i;
  788. X    register char **sp;
  789. X    register char **ep;
  790. X
  791. X    reginput = string;
  792. X    regstartp = prog->startp;
  793. X    regendp = prog->endp;
  794. X
  795. X    sp = prog->startp;
  796. X    ep = prog->endp;
  797. X    for (i = NSUBEXP; i > 0; i--) {
  798. X    *sp++ = NULL;
  799. X    *ep++ = NULL;
  800. X    }
  801. X    if (regmatch(prog->program + 1)) {
  802. X    prog->startp[0] = string;
  803. X    prog->endp[0] = reginput;
  804. X    return (1);
  805. X    } else
  806. X    return (0);
  807. X}
  808. X
  809. X/*
  810. X - regmatch - main matching routine
  811. X *
  812. X * Conceptually the strategy is simple:  check to see whether the current
  813. X * node matches, call self recursively to see whether the rest matches,
  814. X * and then act accordingly.  In practice we make some effort to avoid
  815. X * recursion, in particular by going through "ordinary" nodes (that don't
  816. X * need to know whether the rest of the match failed) by a loop instead of
  817. X * by recursion.
  818. X */
  819. X#ifdef __STDC__
  820. X
  821. Xstatic int regmatch(char *prog)
  822. X
  823. X#else
  824. X
  825. Xstatic int regmatch(prog)
  826. Xchar           *prog;
  827. X
  828. X#endif
  829. X{
  830. X    register char  *scan;    /* Current node. */
  831. X    char           *nxt;    /* nxt node. */
  832. X
  833. X    scan = prog;
  834. X#ifdef DEBUG
  835. X    if (scan != NULL && regnarrate)
  836. X    fprintf(stderr, "%s(\n", regprop(scan));
  837. X#endif
  838. X    while (scan != NULL) {
  839. X#ifdef DEBUG
  840. X    if (regnarrate)
  841. X        fprintf(stderr, "%s...\n", regprop(scan));
  842. X#endif
  843. X    nxt = regnext(scan);
  844. X
  845. X    switch (OP(scan)) {
  846. X    case BOL:
  847. X        if (reginput != regbol)
  848. X        return (0);
  849. X        break;
  850. X    case EOL:
  851. X        if (*reginput != '\0')
  852. X        return (0);
  853. X        break;
  854. X    case ANY:
  855. X        if (*reginput == '\0')
  856. X        return (0);
  857. X        reginput++;
  858. X        break;
  859. X    case EXACTLY:{
  860. X        register int    len;
  861. X        register char  *opnd;
  862. X
  863. X        opnd = OPERAND(scan);
  864. X        /* Inline the first character, for speed. */
  865. X        if (*opnd != *reginput)
  866. X            return (0);
  867. X        len = strlen(opnd);
  868. X        if (len > 1 && strncmp(opnd, reginput, len) != 0)
  869. X            return (0);
  870. X        reginput += len;
  871. X        }
  872. X        break;
  873. X    case ANYOF:
  874. X        if (*reginput == '\0' || strchr(OPERAND(scan), *reginput) == NULL)
  875. X        return (0);
  876. X        reginput++;
  877. X        break;
  878. X    case ANYBUT:
  879. X        if (*reginput == '\0' || strchr(OPERAND(scan), *reginput) != NULL)
  880. X        return (0);
  881. X        reginput++;
  882. X        break;
  883. X    case NOTHING:
  884. X        break;
  885. X    case BACK:
  886. X        break;
  887. X    case OPEN + 1:
  888. X    case OPEN + 2:
  889. X    case OPEN + 3:
  890. X    case OPEN + 4:
  891. X    case OPEN + 5:
  892. X    case OPEN + 6:
  893. X    case OPEN + 7:
  894. X    case OPEN + 8:
  895. X    case OPEN + 9:{
  896. X        register int    no;
  897. X        register char  *save;
  898. X
  899. X        no = OP(scan) - OPEN;
  900. X        save = reginput;
  901. X
  902. X        if (regmatch(nxt)) {
  903. X            /*
  904. X             * Don't set startp if some later invocation of the same
  905. X             * parentheses already has. 
  906. X             */
  907. X            if (regstartp[no] == NULL)
  908. X            regstartp[no] = save;
  909. X            return (1);
  910. X        } else
  911. X            return (0);
  912. X        }
  913. X        break;
  914. X    case CLOSE + 1:
  915. X    case CLOSE + 2:
  916. X    case CLOSE + 3:
  917. X    case CLOSE + 4:
  918. X    case CLOSE + 5:
  919. X    case CLOSE + 6:
  920. X    case CLOSE + 7:
  921. X    case CLOSE + 8:
  922. X    case CLOSE + 9:{
  923. X        register int    no;
  924. X        register char  *save;
  925. X
  926. X        no = OP(scan) - CLOSE;
  927. X        save = reginput;
  928. X
  929. X        if (regmatch(nxt)) {
  930. X            /*
  931. X             * Don't set endp if some later invocation of the same
  932. X             * parentheses already has. 
  933. X             */
  934. X            if (regendp[no] == NULL)
  935. X            regendp[no] = save;
  936. X            return (1);
  937. X        } else
  938. X            return (0);
  939. X        }
  940. X        break;
  941. X    case BRANCH:{
  942. X        register char  *save;
  943. X
  944. X        if (OP(nxt) != BRANCH)    /* No choice. */
  945. X            nxt = OPERAND(scan);    /* Avoid recursion. */
  946. X        else {
  947. X            do {
  948. X            save = reginput;
  949. X            if (regmatch(OPERAND(scan)))
  950. X                return (1);
  951. X            reginput = save;
  952. X            scan = regnext(scan);
  953. X            } while (scan != NULL && OP(scan) == BRANCH);
  954. X            return (0);
  955. X            /* NOTREACHED */
  956. X        }
  957. X        }
  958. X        break;
  959. X    case STAR:{
  960. X        register char   nextch;
  961. X        register int    no;
  962. X        register char  *save;
  963. X        register int    min;
  964. X
  965. X        /*
  966. X         * Lookahead to avoid useless match attempts when we know
  967. X         * what character comes next. 
  968. X         */
  969. X        nextch = '\0';
  970. X        if (OP(nxt) == EXACTLY)
  971. X            nextch = *OPERAND(nxt);
  972. X        min = (OP(scan) == STAR) ? 0 : 1;
  973. X        save = reginput;
  974. X        no = regrepeat(OPERAND(scan));
  975. X        while (no >= min) {
  976. X            /* If it could work, try it. */
  977. X            if (nextch == '\0' || *reginput == nextch)
  978. X            if (regmatch(nxt))
  979. X                return (1);
  980. X            /* Couldn't or didn't -- back up. */
  981. X            no--;
  982. X            reginput = save + no;
  983. X        }
  984. X        return (0);
  985. X        }
  986. X        break;
  987. X    case END:
  988. X        return (1);        /* Success! */
  989. X        break;
  990. X    default:
  991. X        regerror("memory corruption");
  992. X        return (0);
  993. X        break;
  994. X    }
  995. X
  996. X    scan = nxt;
  997. X    }
  998. X
  999. X    /*
  1000. X     * We get here only if there's trouble -- normally "case END" is the
  1001. X     * terminating point. 
  1002. X     */
  1003. X    regerror("corrupted pointers");
  1004. X    return (0);
  1005. X}
  1006. X
  1007. X/*
  1008. X - regrepeat - repeatedly match something simple, report how many
  1009. X */
  1010. X#ifdef __STDC__
  1011. X
  1012. Xstatic int regrepeat(char *p)
  1013. X
  1014. X#else
  1015. X
  1016. Xstatic int regrepeat(p)
  1017. Xchar           *p;
  1018. X
  1019. X#endif
  1020. X{
  1021. X    register int    count = 0;
  1022. X    register char  *scan;
  1023. X    register char  *opnd;
  1024. X
  1025. X    scan = reginput;
  1026. X    opnd = OPERAND(p);
  1027. X    switch (OP(p)) {
  1028. X    case ANY:
  1029. X    count = strlen(scan);
  1030. X    scan += count;
  1031. X    break;
  1032. X    case EXACTLY:
  1033. X    while (*opnd == *scan) {
  1034. X        count++;
  1035. X        scan++;
  1036. X    }
  1037. X    break;
  1038. X    case ANYOF:
  1039. X    while (*scan != '\0' && strchr(opnd, *scan) != NULL) {
  1040. X        count++;
  1041. X        scan++;
  1042. X    }
  1043. X    break;
  1044. X    case ANYBUT:
  1045. X    while (*scan != '\0' && strchr(opnd, *scan) == NULL) {
  1046. X        count++;
  1047. X        scan++;
  1048. X    }
  1049. X    break;
  1050. X    default:            /* Oh dear.  Called inappropriately. */
  1051. X    regerror("internal foulup");
  1052. X    count = 0;        /* Best compromise. */
  1053. X    break;
  1054. X    }
  1055. X    reginput = scan;
  1056. X
  1057. X    return (count);
  1058. X}
  1059. X
  1060. X
  1061. X/*
  1062. X - regnext - dig the "nxt" pointer out of a node
  1063. X */
  1064. X#ifdef __STDC__
  1065. X
  1066. Xstatic char *regnext(register char *p)
  1067. X
  1068. X#else
  1069. X
  1070. Xstatic char *regnext(p)
  1071. Xregister char  *p;
  1072. X
  1073. X#endif
  1074. X{
  1075. X    register int    offset;
  1076. X
  1077. X    if (p == ®dummy)
  1078. X    return (NULL);
  1079. X
  1080. X    offset = NEXT(p);
  1081. X    if (offset == 0)
  1082. X    return (NULL);
  1083. X
  1084. X    if (OP(p) == BACK)
  1085. X    return (p - offset);
  1086. X    else
  1087. X    return (p + offset);
  1088. X}
  1089. X
  1090. X#ifdef DEBUG
  1091. X
  1092. XSTATIC char    *regprop();
  1093. X
  1094. X/*
  1095. X - regdump - dump a regexp onto stdout in vaguely comprehensible form
  1096. X */
  1097. X#ifdef __STDC__
  1098. X
  1099. Xvoid regdump(regexp *r)
  1100. X
  1101. X#else
  1102. X
  1103. Xvoid regdump(r)
  1104. Xregexp         *r;
  1105. X
  1106. X#endif
  1107. X{
  1108. X    register char  *s;
  1109. X    register char   op = EXACTLY;    /* Arbitrary non-END op. */
  1110. X    register char  *nxt;
  1111. X    extern char    *strchr();
  1112. X
  1113. X
  1114. X    s = r->program + 1;
  1115. X    while (op != END) {        /* While that wasn't END last time... */
  1116. X    op = OP(s);
  1117. X    printf("%2d%s", s - r->program, regprop(s));    /* Where, what. */
  1118. X    nxt = regnext(s);
  1119. X    if (nxt == NULL)    /* nxt ptr. */
  1120. X        printf("(0)");
  1121. X    else
  1122. X        printf("(%d)", (s - r->program) + (nxt - s));
  1123. X    s += 3;
  1124. X    if (op == ANYOF || op == ANYBUT || op == EXACTLY) {
  1125. X        /* Literal string, where present. */
  1126. X        while (*s != '\0') {
  1127. X        putchar(*s);
  1128. X        s++;
  1129. X        }
  1130. X        s++;
  1131. X    }
  1132. X    putchar('\n');
  1133. X    }
  1134. X
  1135. X    /* Header fields of interest. */
  1136. X    if (r->regstart != '\0')
  1137. X    printf("start `%c' ", r->regstart);
  1138. X    if (r->reganch)
  1139. X    printf("anchored ");
  1140. X    if (r->regmust != NULL)
  1141. X    printf("must have \"%s\"", r->regmust);
  1142. X    printf("\n");
  1143. X}
  1144. X
  1145. X/*
  1146. X - regprop - printable representation of opcode
  1147. X */
  1148. X#ifdef __STDC__
  1149. X
  1150. Xstatic char *regprop(char *op)
  1151. X
  1152. X#else
  1153. X
  1154. Xstatic char *regprop(op)
  1155. Xchar           *op;
  1156. X
  1157. X#endif
  1158. X{
  1159. X    register char  *p;
  1160. X    static char     buf[50];
  1161. X
  1162. X    strcpy(buf, ":");
  1163. X
  1164. X    switch (OP(op)) {
  1165. X    case BOL:
  1166. X    p = "BOL";
  1167. X    break;
  1168. X    case EOL:
  1169. X    p = "EOL";
  1170. X    break;
  1171. X    case ANY:
  1172. X    p = "ANY";
  1173. X    break;
  1174. X    case ANYOF:
  1175. X    p = "ANYOF";
  1176. X    break;
  1177. X    case ANYBUT:
  1178. X    p = "ANYBUT";
  1179. X    break;
  1180. X    case BRANCH:
  1181. X    p = "BRANCH";
  1182. X    break;
  1183. X    case EXACTLY:
  1184. X    p = "EXACTLY";
  1185. X    break;
  1186. X    case NOTHING:
  1187. X    p = "NOTHING";
  1188. X    break;
  1189. X    case BACK:
  1190. X    p = "BACK";
  1191. X    break;
  1192. X    case END:
  1193. X    p = "END";
  1194. X    break;
  1195. X    case OPEN + 1:
  1196. X    case OPEN + 2:
  1197. X    case OPEN + 3:
  1198. X    case OPEN + 4:
  1199. X    case OPEN + 5:
  1200. X    case OPEN + 6:
  1201. X    case OPEN + 7:
  1202. X    case OPEN + 8:
  1203. X    case OPEN + 9:
  1204. X    sprintf(buf + strlen(buf), "OPEN%d", OP(op) - OPEN);
  1205. X    p = NULL;
  1206. X    break;
  1207. X    case CLOSE + 1:
  1208. X    case CLOSE + 2:
  1209. X    case CLOSE + 3:
  1210. X    case CLOSE + 4:
  1211. X    case CLOSE + 5:
  1212. X    case CLOSE + 6:
  1213. X    case CLOSE + 7:
  1214. X    case CLOSE + 8:
  1215. X    case CLOSE + 9:
  1216. X    sprintf(buf + strlen(buf), "CLOSE%d", OP(op) - CLOSE);
  1217. X    p = NULL;
  1218. X    break;
  1219. X    case STAR:
  1220. X    p = "STAR";
  1221. X    break;
  1222. X    default:
  1223. X    regerror("corrupted opcode");
  1224. X    break;
  1225. X    }
  1226. X    if (p != NULL)
  1227. X    strcat(buf, p);
  1228. X    return (buf);
  1229. X}
  1230. X#endif
  1231. X
  1232. X/*
  1233. X * The following is provided for those people who do not have strcspn() in
  1234. X * their C libraries.  They should get off their butts and do something
  1235. X * about it; at least one public-domain implementation of those (highly
  1236. X * useful) string routines has been published on Usenet.
  1237. X */
  1238. X#ifdef STRCSPN
  1239. X/*
  1240. X * strcspn - find length of initial segment of s1 consisting entirely
  1241. X * of characters not from s2
  1242. X */
  1243. X
  1244. X#ifdef __STDC__
  1245. X
  1246. Xstatic int strcspn(char *s1, char *s2)
  1247. X
  1248. X#else
  1249. X
  1250. Xstatic int strcspn(s1, s2)
  1251. Xchar           *s1;
  1252. Xchar           *s2;
  1253. X
  1254. X#endif
  1255. X{
  1256. X    register char  *scan1;
  1257. X    register char  *scan2;
  1258. X    register int    count;
  1259. X
  1260. X    count = 0;
  1261. X    for (scan1 = s1; *scan1 != '\0'; scan1++) {
  1262. X    for (scan2 = s2; *scan2 != '\0';)    /* ++ moved down. */
  1263. X        if (*scan1 == *scan2++)
  1264. X        return (count);
  1265. X    count++;
  1266. X    }
  1267. X    return (count);
  1268. X}
  1269. X#endif
  1270. X
  1271. X
  1272. X/*
  1273. X - regsub - perform substitutions after a regexp match
  1274. X */
  1275. X#ifdef __STDC__
  1276. X
  1277. Xvoid regsub(regexp *prog, char *source, char *dest)
  1278. X
  1279. X#else
  1280. X
  1281. Xvoid regsub(prog, source, dest)
  1282. Xregexp         *prog;
  1283. Xchar           *source;
  1284. Xchar           *dest;
  1285. X
  1286. X#endif
  1287. X{
  1288. X    register char  *src;
  1289. X    register char  *dst;
  1290. X    register char   c;
  1291. X    register int    no;
  1292. X    register int    len;
  1293. X    extern char    *strncpy();
  1294. X
  1295. X    if (prog == NULL || source == NULL || dest == NULL) {
  1296. X    regerror("NULL parm to regsub");
  1297. X    return;
  1298. X    }
  1299. X    if (UCHARAT(prog->program) != MAGIC) {
  1300. X    regerror("damaged regexp fed to regsub");
  1301. X    return;
  1302. X    }
  1303. X    src = source;
  1304. X    dst = dest;
  1305. X    while ((c = *src++) != '\0') {
  1306. X    if (c == '&')
  1307. X        no = 0;
  1308. X    else if (c == '\\' && '0' <= *src && *src <= '9')
  1309. X        no = *src++ - '0';
  1310. X    else
  1311. X        no = -1;
  1312. X
  1313. X    if (no < 0) {        /* Ordinary character. */
  1314. X        if (c == '\\' && (*src == '\\' || *src == '&'))
  1315. X        c = *src++;
  1316. X        *dst++ = c;
  1317. X    } else if (prog->startp[no] != NULL && prog->endp[no] != NULL) {
  1318. X        len = prog->endp[no] - prog->startp[no];
  1319. X        strncpy(dst, prog->startp[no], len);
  1320. X        dst += len;
  1321. X        if (len != 0 && *(dst - 1) == '\0') {    /* strncpy hit NUL. */
  1322. X        regerror("damaged match string");
  1323. X        return;
  1324. X        }
  1325. X    }
  1326. X    }
  1327. X    *dst++ = '\0';
  1328. X}
  1329. X
  1330. X
  1331. X#ifdef __STDC__
  1332. X
  1333. Xvoid regerror(char *s)
  1334. X
  1335. X#else
  1336. X
  1337. Xvoid regerror(s)
  1338. Xchar           *s;
  1339. X
  1340. X#endif
  1341. X{
  1342. X    fprintf(stderr, "regexp(3): %s", s);
  1343. X    exit(1);
  1344. X}
  1345. END_OF_regexp.c
  1346. if test 30611 -ne `wc -c <regexp.c`; then
  1347.     echo shar: \"regexp.c\" unpacked with wrong size!
  1348. fi
  1349. # end of overwriting check
  1350. fi
  1351. if test -f 'Makefile' -a "${1}" != "-c" ; then 
  1352.   echo shar: Will not clobber existing file \"'Makefile'\"
  1353. else
  1354. echo shar: Extracting \"'Makefile'\" \(3296 characters\)
  1355. sed "s/^X//" >'Makefile' <<'END_OF_FILE'
  1356. X#
  1357. X# PAX - read and write POSIX conformant tar and cpio archives 
  1358. X#
  1359. X# Written by Mark H. Colburn (mark@jhereg.mn.org)
  1360. X#
  1361. X# $Id: Makefile,v 1.1 88/12/23 18:02:42 mark Rel $
  1362. X#
  1363. X
  1364. X#
  1365. X# CONFIGURATION SECTION
  1366. X#
  1367. X# The following defines may need to be changed for each system which PAX
  1368. X# is installed on.  Please review these settings before installing on your
  1369. X# system.
  1370. X
  1371. X#
  1372. X# You should define _POSIX_SOURCE if you are running on a POSIX system.  This
  1373. X# include has to be in the command line because it has to appear before any
  1374. X# include file is included in the source.  For most systems in use today,
  1375. X# it should be left blank.
  1376. X# 
  1377. X# POSIX= -D_POSIX_SOURCE
  1378. XPOSIX= 
  1379. X
  1380. X#
  1381. X# Set CFLAGS to whatever makes your C compiler happy.  Be sure to include 
  1382. X# the definition of $(POSIX) in the flag.
  1383. X#
  1384. XCFLAGS = -O $(POSIX)
  1385. XCC = cc
  1386. X
  1387. X#
  1388. X# Set LFLAGS to whatever makes your linker happy
  1389. X#
  1390. X#LDFLAGS = -s
  1391. XLDFLAGS = 
  1392. X
  1393. X#
  1394. X# Set LINTFLAGS to whatever makes your implementation of lint happy.  If
  1395. X# you don't undef __STDC__ and you have an ANSI C compiler, lint will choke 
  1396. X# on the function prototypes present in func.h
  1397. X#
  1398. XLINTFLAGS = -U__STDC__ $(POSIX)
  1399. X
  1400. X#
  1401. X# BINDIR - points to the directory in which you want the final pax, tar and
  1402. X# cpio binaries installed in.
  1403. X#
  1404. XBINDIR = /usr/local/bin
  1405. X
  1406. X#
  1407. X# MANDIR - specify the directory in which the man pages will be installed
  1408. X#
  1409. XMAN5 = /usr/man/man5
  1410. XMAN1 = /usr/man/man1
  1411. X
  1412. X#
  1413. X# There are three different ways to get POSIX or BSD conformant directory 
  1414. X# access routines: 1) they are installed in your system library, 2) you 
  1415. X# are using Doug Gwyn's dirent library (/usr/lib/libdirent.a), or 3) you 
  1416. X# need the source for the dirent package.  Based on that, pick one of the 
  1417. X# following three options:
  1418. X#
  1419. X# 1. Pick the first dirent line and make sure that config.h is defined
  1420. X#    correctly for your version of directory access routines.  THIS IS
  1421. X#    THE LINE WHICH SHOULD BE USED FOR BSD SYSTEMS.
  1422. X# 2. Chose the second dirent line which  used a library at link time.  You
  1423. X#    may need to change the name of the library to match your system.
  1424. X# 3. If you need #3, then you must copy everything in the subdirectory dirent 
  1425. X#    to this directory and choose the DIROBJ lines.  Please note that this 
  1426. X#    version of dirent has been modified to work as a stand-alone. 
  1427. X#
  1428. XDIRENT=
  1429. X#DIRENT= -ldirent
  1430. X#DIROBJ= paxdir.o
  1431. X
  1432. X#
  1433. X# END CONFIGURATION SECTION 
  1434. X#
  1435. X# Nothing beyond this point should need to be changed.
  1436. X#
  1437. X
  1438. XMISC   = Makefile pax.1 tar.5 cpio.5 README PATCHLEVEL
  1439. XHEADERS= config.h func.h limits.h port.h pax.h 
  1440. XSOURCE= pax.c append.c buffer.c cpio.c create.c extract.c fileio.c\
  1441. X    link.c list.c mem.c namelist.c names.c pass.c pathname.c\
  1442. X    port.c regexp.c replace.c tar.c ttyio.c warn.c wildmat.c
  1443. XOBJECT= pax.o append.o buffer.o cpio.o create.o extract.o fileio.o\
  1444. X    link.o list.o mem.o namelist.o names.o pass.o pathname.o\
  1445. X    port.o regexp.o replace.o tar.o ttyio.o warn.o wildmat.o $(DIROBJ)
  1446. XPROGS = pax tar cpio
  1447. XPMAN1 = pax.1 tar.1
  1448. XPMAN5 = pax.5 tar.5
  1449. X
  1450. Xall: $(PROGS)
  1451. X
  1452. Xinstall: $(PROGS)
  1453. X    mv $(PROGS) $(BINDIR)
  1454. X    cp $(PMAN1) $(MAN1)
  1455. X#    cp $(PMAN5) $(MAN5)
  1456. X
  1457. Xclean:
  1458. X    rm -f $(OBJECT)
  1459. X    rm -f $(PROGS) a.out *.BAK *.bak 
  1460. X
  1461. Xlint:
  1462. X    lint $(LINTFLAGS) $(SOURCE)
  1463. X
  1464. Xpax : $(OBJECT)
  1465. X    $(CC) $(CFLAGS) -o pax $(OBJECT) $(DIRENT) 
  1466. X
  1467. Xtar: pax
  1468. X    rm -f tar
  1469. X    ln pax tar
  1470. X
  1471. Xcpio: pax
  1472. X    rm -f cpio
  1473. X    ln pax cpio
  1474. X
  1475. X$(OBJECT): $(HEADERS)
  1476. END_OF_FILE
  1477. if test 3296 -ne `wc -c <'Makefile'`; then
  1478.     echo shar: \"'Makefile'\" unpacked with wrong size!
  1479. fi
  1480. # end of 'Makefile'
  1481. fi
  1482. echo shar: End of archive 6 \(of 6\).
  1483. cp /dev/null ark6isdone
  1484. MISSING=""
  1485. for I in 1 2 3 4 5 6 ; do
  1486.     if test ! -f ark${I}isdone ; then
  1487.     MISSING="${MISSING} ${I}"
  1488.     fi
  1489. done
  1490. if test "${MISSING}" = "" ; then
  1491.     echo You have unpacked all 6 archives.
  1492.     rm -f ark[1-9]isdone
  1493. else
  1494.     echo You still need to unpack the following archives:
  1495.     echo "        " ${MISSING}
  1496. fi
  1497. ##  End of shell archive.
  1498. exit 0
  1499.  
  1500.